home *** CD-ROM | disk | FTP | other *** search
- <?xml version="1.0"?>
- <xsl:stylesheet version="1.0"
- xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:svg="http://www.w3.org/2000/svg">
- <xsl:output method="xml" indent="yes"/>
- <!-- global variable for bar width -->
- <xsl:variable name="bar_width" select="number(80)"/>
- <!-- spacing between bars -->
- <xsl:variable name="bar_spacing" select="number(10)"/>
- <!-- graph height scaling -->
- <xsl:variable name="graph_height" select="number(500)"/>
- <xsl:variable name="left_margin" select="number(100)"/>
-
- <xsl:template match="/">
- <!-- body root of svg -->
- <svg:svg id="body" viewBox="0 0 -100 {$graph_height + 100}">
- <!-- script for showing/hiding actual value hints on bars -->
- <script type="text/ecmascript"><![CDATA[
- function DoOnOver(evt,HintId){
- // get document...
- var target = evt.getTarget();
- var doc = target.getOwnerDocument();
- // get the hint graphic...
- var Hint = doc.getElementById(HintId);
- // make hint graphic visible...
- Hint.setAttribute('style', 'visibility:visible');
- }
- function DoOnOut(evt,HintId){
- // get document...
- var target = evt.getTarget();
- var doc = target.getOwnerDocument();
- // get the hint graphic...
- var Hint = doc.getElementById(HintId);
- // make hint graphic visible...
- Hint.setAttribute('style', 'visibility:hidden');
- }
- ]]></script>
- <!-- graphic title -->
- <svg:title>Weekly Sales Values</svg:title>
- <!-- main graphic -->
- <svg:g id="barChart" transform="translate(10, 10)" fill-rule="nonzero" clip-rule="nonzero" stroke="none" class="legend"
- stroke-width="1" stroke-linecap="square" stroke-miterlimit="1" style="text-anchor:start" shape-rendering="crispEdges">
- <!-- apply data -->
- <xsl:apply-templates select="sales_summary"/>
- <svg:text transform="matrix(2 0 0 2 {$left_margin} {$graph_height + 70})">Weekly Total Sales Values</svg:text>
- </svg:g>
- </svg:svg>
- </xsl:template>
-
- <!-- main data template -->
- <xsl:template match="sales_summary">
- <!-- calculate the number of weeks -->
- <xsl:variable name="weeks_count" select="count(weekly_sales)"/>
- <!-- calculate the maximum weekly sales value -->
- <xsl:variable name="max_week_sales_value">
- <xsl:for-each select="weekly_sales">
- <xsl:sort select="sum(product_sales/@value)" data-type="number" order="descending"/>
- <xsl:if test="position() = 1">
- <xsl:value-of select="sum(product_sales/@value)"/>
- </xsl:if>
- </xsl:for-each>
- </xsl:variable>
- <!-- max graph height is max sales rounded to next 100 -->
- <xsl:variable name="max_graph_height" select="floor(($max_week_sales_value + 99) div 100) * 100"/>
- <!-- draw graph background -->
- <xsl:call-template name="draw_graph">
- <xsl:with-param name="max_graph_height" select="$max_graph_height"/>
- <xsl:with-param name="bar_count" select="$weeks_count"/>
- </xsl:call-template>
- <!-- draw the graph bars themselves from data -->
- <xsl:apply-templates select="weekly_sales">
- <xsl:sort select="@week_no" data-type="number"/>
- <xsl:with-param name="max_graph_height" select="$max_graph_height"/>
- </xsl:apply-templates>
- </xsl:template>
-
- <!-- draw graph background and vertical scale/legends -->
- <xsl:template name="draw_graph">
- <xsl:param name="max_graph_height"/>
- <xsl:param name="bar_count"/>
- <xsl:variable name="actual_width" select="($bar_count * ($bar_width + $bar_spacing)) + $bar_spacing"/>
- <svg:g id="GridAndLegend" style="stroke:none;" shape-rendering="crispEdges" stroke-width="1">
- <!-- back face and surrounding lines -->
- <svg:path fill="lightgray" stroke="black" d="M {$left_margin},{$graph_height + 20} h{$actual_width} v-{$graph_height} h-{$actual_width} v{$graph_height}"/>
- <!-- draw zero mark and legend -->
- <svg:path fill="none" stroke="black" d="M {$left_margin - 10},{$graph_height + 20} h10"/>
- <svg:text text-anchor="end" baseline-shift="-3" transform="matrix(1 0 0 1 {$left_margin - 15} {$graph_height + 20})">0</svg:text>
- <!-- draw vertical lines and legends -->
- <xsl:call-template name="draw_graph_vertical_legends">
- <xsl:with-param name="max" select="$max_graph_height"/>
- <xsl:with-param name="legend_threshold" select="$max_graph_height div $graph_height"/>
- <xsl:with-param name="actual_width" select="$actual_width"/>
- </xsl:call-template>
- </svg:g>
- </xsl:template>
-
- <!-- recursive template to draw vertical lines and legends -->
- <xsl:template name="draw_graph_vertical_legends">
- <xsl:param name="max"/>
- <xsl:param name="legend_threshold"/>
- <xsl:param name="actual_width"/>
- <!-- params used only during recursion -->
- <xsl:param name="start" select="number(100)"/>
- <xsl:param name="step" select="number(100)"/>
- <xsl:param name="prev_marked_start" select="number(0)"/>
- <!-- calculate actual vertical 'pixel' position for this mark and previous drawn mark -->
- <xsl:variable name="prev_vert_posn" select="($prev_marked_start div $max) * $graph_height"/>
- <xsl:variable name="vert_posn" select="($start div $max) * $graph_height"/>
- <!-- work out whether this line is too close to previous line -->
- <xsl:variable name="new_marked_start">
- <xsl:choose>
- <xsl:when test="($vert_posn - $prev_vert_posn) >= $legend_threshold">
- <xsl:value-of select="$start"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$prev_marked_start"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <!-- only draw line and legend when not too close -->
- <xsl:if test="$new_marked_start = $start">
- <svg:path fill="none" stroke="black" d="M {$left_margin - 10},{$graph_height + 20 - floor($vert_posn)} h{$actual_width + 10}"/>
- <svg:text text-anchor="end" baseline-shift="-3" transform="matrix(1 0 0 1 {$left_margin - 15} {$graph_height + 20 - floor($vert_posn)})">
- <xsl:value-of select="$start"/>
- </svg:text>
- </xsl:if>
- <!-- if not yet reached max then recurse call to this template -->
- <xsl:if test="$start < $max">
- <xsl:call-template name="draw_graph_vertical_legends">
- <xsl:with-param name="max" select="$max"/>
- <xsl:with-param name="legend_threshold" select="$legend_threshold"/>
- <xsl:with-param name="actual_width" select="$actual_width"/>
- <xsl:with-param name="start" select="$start + $step"/>
- <xsl:with-param name="step" select="$step"/>
- <xsl:with-param name="prev_marked_start" select="$new_marked_start"/>
- </xsl:call-template>
- </xsl:if>
- </xsl:template>
-
- <!-- applied template that draws bar for each week -->
- <xsl:template match="weekly_sales">
- <xsl:param name="max_graph_height"/>
- <!-- draw the bar for this week sales value -->
- <xsl:variable name="sales_value" select="sum(product_sales/@value)"/>
- <xsl:variable name="bar_height" select="floor(($sales_value div $max_graph_height) * $graph_height)"/>
- <xsl:variable name="bar_left" select="((position() - 1) * ($bar_width + $bar_spacing)) + $bar_spacing"/>
- <!-- draw the bar -->
- <svg:path fill="lime" stroke="none" d="M {$bar_left + $left_margin},{$graph_height + 19} h{$bar_width} v-{$bar_height} h-{$bar_width} v{$bar_height}"
- onmouseover="DoOnOver(evt,'Hint_{@week_no}')" onmouseout="DoOnOut(evt,'Hint_{@week_no}')"/>
- <!-- draw the legend -->
- <svg:text text-anchor="middle" transform="matrix(1.5 0 0 1.5 {$left_margin + $bar_left + ($bar_width div 2)} {$graph_height + 40})">
- <xsl:text>Week </xsl:text>
- <xsl:value-of select="@week_no"/>
- </svg:text>
- <!-- create the invisible hint info for the bar -->
- <svg:g id="Hint_{@week_no}" style="visibility: hidden;">
- <svg:path fill="none" stroke="red" d="M {$left_margin - 10},{$graph_height + 20 - $bar_height} h{$bar_left + 10}"/>
- <svg:text transform="matrix(1 0 0 1 {$left_margin + $bar_left + 2} {($graph_height + 30) - $bar_height})">
- <xsl:value-of select="format-number($sales_value,'#,##0')"/>
- </svg:text>
- </svg:g>
- </xsl:template>
- </xsl:stylesheet>